/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.refunite.mobile.webservice.formgenerator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import org.refunite.mobile.webservice.bindings.formgenerator.Bind;
import org.refunite.mobile.webservice.bindings.formgenerator.Body;
import org.refunite.mobile.webservice.bindings.formgenerator.Head;
import org.refunite.mobile.webservice.bindings.formgenerator.Html;
import org.refunite.mobile.webservice.bindings.formgenerator.Input;
import org.refunite.mobile.webservice.bindings.formgenerator.Instance;
import org.refunite.mobile.webservice.bindings.formgenerator.Item;
import org.refunite.mobile.webservice.bindings.formgenerator.Itext;
import org.refunite.mobile.webservice.bindings.formgenerator.Label;
import org.refunite.mobile.webservice.bindings.formgenerator.Model;
import org.refunite.mobile.webservice.bindings.formgenerator.RegistrationForm;
import org.refunite.mobile.webservice.bindings.formgenerator.Select1;
import org.refunite.mobile.webservice.bindings.formgenerator.Text;
import org.refunite.mobile.webservice.bindings.formgenerator.Translation;

/**
 *
 * @author I040022
 */
public class FormGenerator {

    private static HashMap<String, ArrayList<Text>> languages = new HashMap<String, ArrayList<Text>>();

    private static String generateRefAttributeForQuestionItem(String id){
        return "/RegistrationForm/"+id;
    }
    private static Label generateLabel(String id){
        Label label = new Label();
        label.setRef("jr:itext('"+id+"')");
        return label;
    }
    private static Itext generateItextTag(ArrayList<AbstractQuestion> questionList){
        Itext retValue = new Itext();
        for(AbstractQuestion question : questionList){
            for(TextItem questionText : question.getQuestionTextList()){
                String lang = questionText.getLanguage();
                ArrayList<Text> textList = languages.get(lang);
                if(textList == null){
                    textList = new ArrayList<Text>();
                    languages.put(lang, textList);
                }
                Text text = new Text();
                text.setId(question.getId());
                text.setValue(questionText.getText());
                textList.add(text);
            }
            // if the question type select, collect texts from select options
            if(question.getInputType() == AbstractQuestion.TYPE_INPUT_SELECT){
                SelectQuestion selectionQuestion = (SelectQuestion)question;
                ArrayList<SelectOption> selectOptions = selectionQuestion.getSelectOptions();
                for(SelectOption selectOption : selectOptions){
                    for(TextItem optionLabel : selectOption.getLabels()){
                        String lang = optionLabel.getLanguage();
                        ArrayList<Text> textList = languages.get(lang);
                        if(textList == null){
                            textList = new ArrayList<Text>();
                            languages.put(lang, textList);
                        }
                        Text text = new Text();
                        text.setId(selectOption.getId());
                        text.setValue(optionLabel.getText());
                        textList.add(text);
                    }
                }
            }
        }
        Iterator<String> it = languages.keySet().iterator();
        while(it.hasNext()){
            String lang = it.next();
            Translation translation = new Translation();
            translation.setLang(lang);
            ArrayList<Text> translatedText = languages.get(lang);
            for(Text text : translatedText){
                translation.getText().add(text);
            }
            retValue.getTranslation().add(translation);
        }
        return retValue;
    }

    private static RegistrationForm generateRegistrationFormInstance(FormStructure formStructure){
        RegistrationForm retValue = new RegistrationForm();
        ArrayList<AbstractQuestion> questionList = formStructure.getQuestionList();
        for(AbstractQuestion question : questionList){
            JAXBElement aa = new JAXBElement(new QName(question.getId()), String.class, new String());
            retValue.getAny().add(aa);
        }
        return retValue;
    }

    private static Select1 generateSelect1(SelectQuestion question){
        Select1 select1 = new Select1();
        select1.setAppearance("minimal");
        select1.setLabel(generateLabel(question.getId()));
        select1.setRef(generateRefAttributeForQuestionItem(question.getId()));
        // create select items
        for(SelectOption selectOption : question.getSelectOptions()){
            Item item = new Item();
            item.setLabel(generateLabel(selectOption.getId()));
            item.setValue(selectOption.getValue());
            select1.getItem().add(item);
        }
        return select1;
    }
    private static Input generateInput(AbstractQuestion question){
        Input retValue = new Input();
        retValue.setLabel(generateLabel(question.getId()));
        retValue.setRef(generateRefAttributeForQuestionItem(question.getId()));
        return retValue;
    }
    private static Body generateBody(ArrayList<AbstractQuestion> questionList){
        Body retValue = new Body();
        for(AbstractQuestion question : questionList){
            switch(question.getInputType()){
                case AbstractQuestion.TYPE_INPUT_TEXT:
                    retValue.getInputOrSelect1().add(generateInput((SimpleQuestion)question));
                    break;
                case AbstractQuestion.TYPE_INPUT_SELECT:
                    retValue.getInputOrSelect1().add(generateSelect1((SelectQuestion)question));
                    break;
            }
        }
        return retValue;
    }
    public static Html generateForm(FormStructure formStructure){
        languages = new HashMap<String, ArrayList<Text>>();

        Html formInstance = new Html();
        Head head = new Head();
        head.setTitle(formStructure.getFormTitle());
        Model model = new Model();
        Itext itext = generateItextTag(formStructure.getQuestionList());
        model.setItext(itext);
        head.setModel(model);
        formInstance.setHead(head);

        Instance instance = new Instance();
        RegistrationForm form = generateRegistrationFormInstance(formStructure);
        instance.setRegistrationForm(form);
        model.setInstance(instance);

        for(AbstractQuestion question : formStructure.getQuestionList()){
            Bind bind = new Bind();
            bind.setNodeset(generateRefAttributeForQuestionItem(question.getId()));
            bind.setType(question.getDataType());
            if(question.isRequired()){
                bind.setRequired("true()");
            }
            if(question.getConstraintMessage() != null && question.getConstraintMessage().length() > 0){
                bind.setConstraintMsg(question.getConstraintMessage());
            }
            if(question.getConstraint() != null && question.getConstraint().length() > 0){
                bind.setConstraint(question.getConstraint());
            }
            if(question.getRelevant() != null && question.getRelevant().length() > 0){
                bind.setRelevant(question.getRelevant());
            }
            model.getBind().add(bind);
        }

        Body body = generateBody(formStructure.getQuestionList());
        formInstance.setBody(body);
        return formInstance;
    }
}
